// -*-mode:c++; coding:utf-8-*-

#ifndef _STACK_OR_HEAP_ARRAY_HPP_
#define _STACK_OR_HEAP_ARRAY_HPP_

#include "config.hpp"

template<std::size_t integer1, std::size_t integer2>
struct less_than_or_equal_to
{
	enum { value = (integer1 <= integer2) };
};

template<typename Allocator, std::size_t size, bool on_stack>
struct stack_or_heap_array_helper;

// stack version
template<typename Allocator, std::size_t size>
struct stack_or_heap_array_helper<Allocator, size, true>
{
	char data[size];

	char *get() { return data; }
	const char *get() const { return data; }
};

// heap version
template<typename Allocator, std::size_t size>
struct stack_or_heap_array_helper<Allocator, size, false>
{
	char *data;
	Allocator m_alloc;

	stack_or_heap_array_helper()
		: data(NULL)
		, m_alloc() {
		data = m_alloc.allocate(size);
	}

	~stack_or_heap_array_helper() {
		m_alloc.deallocate(data, size);
	}

	char *get() { return data; }
	const char *get() const { return data; }
};

template<unsigned int size, unsigned int threshold = 1024 * 1024> // 1M
struct stack_or_heap_array
	: public stack_or_heap_array_helper<xbase::default_char_allocator,
					    size,
					    less_than_or_equal_to<size, threshold>::value >
{};

#endif	// _STACK_OR_HEAP_ARRAY_HPP_
